package self.sn.chat.core;

import self.sn.chat.ui.MyFrame;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;

public class NIOClient {

    private final ByteBuffer sendBuffer = ByteBuffer.allocate(10240);
    private final ByteBuffer receiveBuffer = ByteBuffer.allocate(10240);
    private final MyFrame myFrame;
    private boolean sendFlag = false;
    private Selector selector = null;

    public void init() throws IOException {
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.connect(new InetSocketAddress(InetAddress.getLocalHost(),8080));
        socketChannel.configureBlocking(false);
        System.out.println("与服务器的连接建立成功");
        selector=Selector.open();
        socketChannel.register(selector, SelectionKey.OP_READ);

        //注册键盘事件
        JTextArea sendMsgArea = myFrame.getSendMsgArea();
        myFrame.getSendBtn().addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (sendMsgArea.getText().isBlank()) return;
                try {
                    send(socketChannel, sendMsgArea.getText().getBytes(StandardCharsets.UTF_8));
                    sendMsgArea.setText("");
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        });

        sendMsgArea.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                //回车发送
                if (e.getKeyCode() == '\n' && !sendMsgArea.getText().isBlank()) {
                    try {
                        send(socketChannel, sendMsgArea.getText().getBytes(StandardCharsets.UTF_8));
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                    sendFlag = true;
                }
            }
            @Override
            public void keyReleased(KeyEvent e) {
                if (e.getKeyCode() == '\n' && sendFlag)
                {
                    sendMsgArea.setText("");
                    sendFlag = false;
                }
            }
        });
        talk();
    }

    public NIOClient(MyFrame myFrame) throws IOException {
        this.myFrame = myFrame;
        init();
    }

    private void talk()throws IOException {
        while (selector.select() > 0 ){
            Iterator<SelectionKey> it = selector.selectedKeys().iterator();
            while (it.hasNext()) {
                SelectionKey key = it.next();
                it.remove();
                if (key.isReadable()) {
                    receive(key);
                }
            }
        }
    }

    private void send(SocketChannel socketChannel,byte[] bytes)throws IOException{
        sendBuffer.clear();
        sendBuffer.put(bytes);
        sendBuffer.flip(); //设置写
        while(sendBuffer.hasRemaining()){
            socketChannel.write(sendBuffer);
        }
        sendBuffer.compact();
    }

    private void receive(SelectionKey key)throws IOException{
        SocketChannel socketChannel=(SocketChannel)key.channel();
        socketChannel.read(receiveBuffer);
        receiveBuffer.flip();

        int op = receiveBuffer.get();
        String receiveData= StandardCharsets.UTF_8.decode(receiveBuffer).toString();
        receiveBuffer.clear();

        switch (op) {
            case 0:
                myFrame.paintTxt(MyFrame.Op.MSG, receiveData + "\n");break;
            case 2:
                myFrame.paintTxt(MyFrame.Op.ONLINE,receiveData);break;
            default:
        }
    }


}
